package com.atguigu.lease.web.admin.service.impl;

import com.atguigu.lease.common.advice.LeaseException;
import com.atguigu.lease.common.result.ResultCodeEnum;
import com.atguigu.lease.model.entity.*;
import com.atguigu.lease.model.enums.ItemType;
import com.atguigu.lease.web.admin.mapper.ApartmentInfoMapper;
import com.atguigu.lease.web.admin.service.*;
import com.atguigu.lease.web.admin.vo.apartment.ApartmentDetailVo;
import com.atguigu.lease.web.admin.vo.apartment.ApartmentItemVo;
import com.atguigu.lease.web.admin.vo.apartment.ApartmentQueryVo;
import com.atguigu.lease.web.admin.vo.apartment.ApartmentSubmitVo;
import com.atguigu.lease.web.admin.vo.graph.GraphVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * @author liubo
 * @description 针对表【apartment_info(公寓信息表)】的数据库操作Service实现
 * @createDate 2023-07-24 15:48:00
 */
@Service
public class ApartmentInfoServiceImpl extends ServiceImpl<ApartmentInfoMapper, ApartmentInfo>
        implements ApartmentInfoService {
    @Autowired
    private ApartmentInfoMapper apartmentInfoMapper;
    @Autowired
    private ApartmentFacilityService apartmentFacilityService;
    @Autowired
    private GraphInfoService graphInfoService;
    @Autowired
    private ApartmentFeeValueService apartmentFeeValueService;
    @Autowired
    private ApartmentLabelService apartmentLabelService;
    @Autowired
    private ProvinceInfoService provinceInfoService;
    @Autowired
    private CityInfoService cityInfoService;
    @Autowired
    private DistrictInfoService districtInfoService;
    @Autowired
    private RoomInfoService roomInfoService;


    /**
     * 根据项目ID和类型删除相关子表数据
     * 此方法旨在清理与给定项目ID和类型相关的多个子表中的数据，以维护数据一致性
     * 例如，当一个项目被删除时，与之相关的图形信息、设施信息、费用信息和标签信息等子表数据也需要被清理
     *
     * @param id 项目ID，用于标识要删除的项目
     * @param type 项目类型，与ID一起使用以精确指定要删除的数据类型
     */
    public void deleteSonTable(Long id, ItemType type){
        // 删除图形信息表中与给定项目ID和类型匹配的记录
        LambdaQueryWrapper<GraphInfo> graphInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
        graphInfoLambdaQueryWrapper.eq(GraphInfo::getItemId, id);
        graphInfoLambdaQueryWrapper.eq(GraphInfo::getItemType, type);
        graphInfoService.remove(graphInfoLambdaQueryWrapper);

        // 删除公寓设施表中与给定公寓ID匹配的记录
        LambdaQueryWrapper<ApartmentFacility> apartmentFacilityLambdaQueryWrapper = new LambdaQueryWrapper<>();
        apartmentFacilityLambdaQueryWrapper.eq(ApartmentFacility::getApartmentId, id);
        apartmentFacilityService.remove(apartmentFacilityLambdaQueryWrapper);

        // 删除公寓费用值表中与给定公寓ID匹配的记录
        LambdaQueryWrapper<ApartmentFeeValue> apartmentFeeValueLambdaQueryWrapper = new LambdaQueryWrapper<>();
        apartmentFeeValueLambdaQueryWrapper.eq(ApartmentFeeValue::getApartmentId, id);
        apartmentFeeValueService.remove(apartmentFeeValueLambdaQueryWrapper);

        // 删除公寓标签表中与给定公寓ID匹配的记录
        LambdaQueryWrapper<ApartmentLabel> apartmentLabelLambdaQueryWrapper = new LambdaQueryWrapper<>();
        apartmentLabelLambdaQueryWrapper.eq(ApartmentLabel::getApartmentId, id);
        apartmentLabelService.remove(apartmentLabelLambdaQueryWrapper);
    }











    @Override
    public void customPage(Page<ApartmentItemVo> page, ApartmentQueryVo queryVo) {
        apartmentInfoMapper.customSelectPage(page, queryVo);
    }

    /**
     * 保存或更新公寓提交信息
     * <p>
     * 该方法首先根据提交的公寓信息中的省份、城市和区域ID获取对应的名称信息，
     * 然后保存或更新公寓信息如果公寓已存在，则删除与该公寓关联的图形信息、
     * 设施信息、费用信息和标签信息，以准备重新保存最新的信息最后，根据提交的
     * 图形信息、设施信息、费用信息和标签信息，分别构建相应的实体列表，并批量保存
     *
     * @param apartmentSubmitVo 公寓提交信息对象，包含公寓的各种信息，如省份ID、城市ID、区域ID、图形信息、设施信息、费用信息和标签信息
     */
    @Override
    public void customSave(ApartmentSubmitVo apartmentSubmitVo) {
        // 判断公寓信息是否已存在
        Boolean exits = apartmentSubmitVo.getId() != null;

        // 根据省份ID获取省份信息
        ProvinceInfo provinceInfo = provinceInfoService.getById(apartmentSubmitVo.getProvinceId());
        // 根据城市ID获取城市信息
        CityInfo cityInfo = cityInfoService.getById(apartmentSubmitVo.getCityId());
        // 根据区域ID获取区域信息
        DistrictInfo districtInfo = districtInfoService.getById(apartmentSubmitVo.getDistrictId());

        // 设置公寓提交信息中的省份名称
        apartmentSubmitVo.setProvinceName(provinceInfo.getName());
        // 设置公寓提交信息中的城市名称
        apartmentSubmitVo.setCityName(cityInfo.getName());

        // 构建查询条件，用于获取指定城市下的所有区域信息
        LambdaQueryWrapper<DistrictInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DistrictInfo::getCityId, cityInfo.getId());
        List<DistrictInfo> list = districtInfoService.list(wrapper);

        // 如果列表不为空，则设置公寓提交信息中的区域名称
        if (list != null) {
            apartmentSubmitVo.setDistrictName(districtInfo.getName());
        }

        // 保存或更新公寓提交信息
        saveOrUpdate(apartmentSubmitVo);

        // 如果公寓信息已存在，则删除与该公寓关联的图形信息、设施信息、费用信息和标签信息
        if (exits) {
            deleteSonTable(apartmentSubmitVo.getId(),ItemType.APARTMENT);
        }

        // 获取公寓提交信息中的图形信息列表
        List<GraphVo> graphVoList = apartmentSubmitVo.getGraphVoList();
        // 如果图形信息列表不为空，则构建图形信息实体列表并保存
        if (!CollectionUtils.isEmpty(graphVoList)) {
            List<GraphInfo> graphInfoList = new ArrayList<>(graphVoList.size());
            for (GraphVo graphVo : graphVoList) {
                GraphInfo graphInfo = new GraphInfo();
                graphInfo.setName(graphVo.getName());
                graphInfo.setUrl(graphVo.getUrl());
                graphInfo.setItemId(apartmentSubmitVo.getId());
                graphInfo.setItemType(ItemType.APARTMENT);
                graphInfoList.add(graphInfo);
            }
            graphInfoService.saveBatch(graphInfoList);
        }

        // 获取公寓提交信息中的设施信息ID列表
        List<Long> facilityInfoIds = apartmentSubmitVo.getFacilityInfoIds();
        // 如果设施信息ID列表不为空，则构建公寓设施信息实体列表并保存
        if (!CollectionUtils.isEmpty(facilityInfoIds)) {
            List<ApartmentFacility> apartmentFacilityList = new ArrayList<>(facilityInfoIds.size());
            for (Long facilityInfoId : facilityInfoIds) {
                ApartmentFacility apartmentFacility = ApartmentFacility.builder()
                        .apartmentId(apartmentSubmitVo.getId())
                        .facilityId(facilityInfoId).build();
                apartmentFacilityList.add(apartmentFacility);
            }
            apartmentFacilityService.saveBatch(apartmentFacilityList);
        }

        // 获取公寓提交信息中的费用信息ID列表
        List<Long> feeValueIds = apartmentSubmitVo.getFeeValueIds();
        // 如果费用信息ID列表不为空，则构建公寓费用信息实体列表并保存
        if (!CollectionUtils.isEmpty(feeValueIds)) {
            List<ApartmentFeeValue> apartmentFeeValueList = new ArrayList<>(feeValueIds.size());
            for (Long feeValueId : feeValueIds) {
                ApartmentFeeValue apartmentFeeValue = ApartmentFeeValue.builder()
                        .feeValueId(feeValueId)
                        .apartmentId(apartmentSubmitVo.getId())
                        .build();
                apartmentFeeValueList.add(apartmentFeeValue);
            }
            apartmentFeeValueService.saveBatch(apartmentFeeValueList);
        }

        // 获取公寓提交信息中的标签信息ID列表
        List<Long> labelIds = apartmentSubmitVo.getLabelIds();
        // 如果标签信息ID列表不为空，则构建公寓标签信息实体列表并保存
        if (!CollectionUtils.isEmpty(labelIds)) {
            List<ApartmentLabel> apartmentLabelList = new ArrayList<>(labelIds.size());
            for (Long labelId : labelIds) {
                ApartmentLabel apartmentLabel = ApartmentLabel.builder()
                        .apartmentId(apartmentSubmitVo.getId())
                        .labelId(labelId)
                        .build();
                apartmentLabelList.add(apartmentLabel);
            }
            apartmentLabelService.saveBatch(apartmentLabelList);
        }
    }

    @Override
    public ApartmentDetailVo customGetById(Long id) {
        return apartmentInfoMapper.customSelectById(id);
    }

    /**
     * 根据ID自定义删除方法
     * 在删除当前实体之前，检查关联的房间信息表中是否存在相关记录
     * 如果存在，则抛出删除异常，表示无法删除
     * 如果不存在，则继续执行删除操作，并删除子表相关记录
     *
     * @param id 要删除的实体的ID
     */
    @Override
    public void customRemoveById(Long id) {
        // 创建查询条件，检查关联的房间信息表中是否存在相关记录
        LambdaQueryWrapper<RoomInfo> wrapper=new LambdaQueryWrapper<>();
        wrapper.eq(RoomInfo::getApartmentId,id);
        // 计算关联表中符合条件的记录数
        long count = roomInfoService.count(wrapper);
        // 如果关联表中存在相关记录，则抛出删除异常，表示无法删除
        if(count>0){
            throw new LeaseException(ResultCodeEnum.DELETE_ERROR);
        }
        // 删除子表相关记录
        deleteSonTable(id,ItemType.APARTMENT);
        // 根据ID删除当前实体
        removeById(id);
    }
}




